package net.niufei.busi;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import net.niufei.DataBuffer;
import net.niufei.buffer.DataBufferFactory;

public class BusiBeanUtil {

	public static DataBuffer parse(BusiBean bean) {
		DataBuffer buffer = DataBufferFactory.allocate(1024);
		Class<?> clazz = bean.getClass();
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			Map<String, PropertyDescriptor> pds = new HashMap<String, PropertyDescriptor>();
			for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
				pds.put(pd.getName(), pd);
			}
			
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				String propertyName = field.getName();
				if(field.isAnnotationPresent(BusiElement.class)) {
					BusiElement busiElement = field.getAnnotation(BusiElement.class);
					if(busiElement.ignore() || !pds.containsKey(propertyName)) {
						continue;
					}
					PropertyDescriptor pd = pds.get(propertyName);
					Method getter = pd.getReadMethod();
					Object obj = getter.invoke(bean, new Object[0]);
					switch(busiElement.type()) {
					case Byte:
						putByte(buffer, obj);
						break;
					case Short:
						putShort(buffer, obj);
						break;
					case Int:
						putInt(buffer, obj);
						break;
					case SLong:
						putSLong(buffer, obj);
						break;
					case Long:
						putLong(buffer, obj);
						break;
					case String:
						putString(buffer, obj);
						break;
					case ByteArray:
						putByteArray(buffer, obj);
						break;
					}
				}
			}
			return buffer;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	private static void putByte(DataBuffer buffer, Object obj) {
		checkObj(obj);
		buffer.put((Byte)obj);
	}
	
	private static void putShort(DataBuffer buffer, Object obj) {
		checkObj(obj);
		buffer.putShort((Short)obj);
	}
	
	private static void putInt(DataBuffer buffer, Object obj) {
		checkObj(obj);
		buffer.putInt((Integer)obj);
	}
	
	private static void putSLong(DataBuffer buffer, Object obj) {
		checkObj(obj);
		buffer.putShortLong((Long)obj);
	}
	
	private static void putLong(DataBuffer buffer, Object obj) {
		checkObj(obj);
		buffer.putLong((Long)obj);
	}
	
	private static void putString(DataBuffer buffer, Object obj) {
		String str = obj == null ? "" : (String)obj;
		buffer.putString(str);
	}
	
	private static void putByteArray(DataBuffer buffer, Object obj) {
		byte[] byteArr = obj == null ? new byte[0] : (byte[])obj;
		buffer.put(byteArr);
	}
	
	private static void checkObj(Object obj) {
		if(obj == null) {
			throw new IllegalArgumentException();
		}
	}
}
